﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Net;
using System.Net.Sockets;

using modDatos;
using modPeticiones;

using System.Threading;

namespace modLanGame
{
    public static class CCliente
    {
        static public CCliente_Datos data;
        static public bool empesarJuego { get; set; }

        static public byte[] DatosEnviar {get; set;}

       // static public Thread hiloRecivir2 = new Thread(new ThreadStart(RecivirInfo2));
       // static public Thread hiloEnviar2 = new Thread(new ThreadStart(EnviarInfo2));

        //almaceno todo los datos que me envio el server de los actores
        //cuando en el gameloop de escenario termine el ensayo, detiene el hilo de receiv, y 
        //le da los datos de esta clase al SCpeticiones 
        static public List<pqActorMini_Datos> datosMini { get; set; }
        static public List<CBalasDatos> Disparos { get; set; }
        static public List<CAsteroidesDatos> Asteroides { get; set; }

        /*Mi direccionaro que almacena los datos de os objetos de los cliente*/
        //static Dictionary<string, pqEstado_dat>[] Jugadores;

        public static void Init(string servidor)
        {
            data = new CCliente_Datos();
            data.ipServer = servidor;

            empesarJuego = false;
            datosMini = new List<pqActorMini_Datos>();

            DatosEnviar = new byte[2548];
        }

        static public void Conectar2()
        {
            try
            {
                byte[] buffByte = new byte[2048];
                pqCmd pqComand = new pqCmd();
                string[] comandos;

                //1° Me presento contra el sock 7300
                Socket sockLogin = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                sockLogin.Connect(IPAddress.Parse(data.ipServer), 7300);
            
                pqComand.data.command = "Conectar";
                sockLogin.Send(pqComand.outByte());

                Console.WriteLine("enviado #conectar#");

                //2° Espero a que el server me de los datos para configurar mi sck dedicado
                sockLogin.Receive(buffByte);
                pqComand.inByte(buffByte);
                comandos = pqComand.data.command.Split('~');

                //obtengo la ip local que use para conectarme al svr, si tengo muchas redes. tambien se puede haber echo calculandolo con mascara de subred
                string[] miAddress = comandos[1].Split(':');

                //creo lo que puedo de los socket dedicados
                data.sockIN = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                data.sockOUT = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                int portDedicado = int.Parse(comandos[0]);

                IPEndPoint buffEndPoint = new IPEndPoint(IPAddress.Parse(miAddress[0]), int.Parse(comandos[0]) + 5);
                data.sockIN.Bind(buffEndPoint);
                data.sockIN.Listen(10);

                //3° envio el comando para empesar a testearla conexion
                pqComand.data.command = "sckDedicado";
                sockLogin.Send(pqComand.outByte());

                //4° espero que el svr me confirme que empiese el test
                sockLogin.Receive(buffByte);
                pqComand.inByte(buffByte);
                comandos = pqComand.data.command.Split('~');

                if (comandos[0] == "RunTest")
                {
                    //5° comienzo la prueba

                    //el svr tsteara primero su IN esperando que le de mi IP
                    data.sockOUT.Connect(data.ipServer, portDedicado);
                    pqComand.data.command = miAddress[0];
                    data.sockOUT.Send(pqComand.outByte());

                    Console.WriteLine("Paq sock OUT enviado");

                    //luego espero la conecion por el mi sock IN
                    data.sockIN = data.sockIN.Accept();                    
                    data.sockIN.Receive(buffByte);

                    Console.WriteLine("Paq sock IN recivido");

                    pqComand.inByte(buffByte);
                    comandos = pqComand.data.command.Split('~');

                    if (comandos[0] == "ProbandoSckOUT")
                    {
                        data.miID = int.Parse(comandos[1]);
                        data.cantJugadores = int.Parse(comandos[2]);

                        Console.WriteLine("Coneccion establecida");
                        EsperarOkJugar();
                    }
                    else
                    {
                        Console.WriteLine("No se pudo establecer la coneccion");
                    }

                }               

            }
            catch (Exception ex)
            {
                string lal = ex.ToString();
                throw;
            }
        }

        static public void EsperarOkJugar()
        { 
            byte[] buffByte = new byte[2048];
            data.sockIN.Receive(buffByte);

            pqCmd comando = new pqCmd();
            comando.inByte(buffByte);

            string[] comands = comando.data.command.Split('~');

            if (comands[0] == "JugarNow")
            {
                data.miID = int.Parse(comands[1]);
                empesarJuego = true;
            }
        }

        #region
        /*
        static public void EnviarInfo()
        {
            pqCmd cmd = new pqCmd();
            pqActorMini actorMini = new pqActorMini();
            pqBalas bala = new pqBalas();
            pqAsteoirdes asteroide = new pqAsteoirdes();

            byte[] buffByte = new byte[2048];
            int debugin = 0;
            string cmdParametres="";

             //creo el cmd de los datos a enviar
            //armo el de balas
            Dictionary<string, CDataGameBase> misNuevasBalas = SCPeticion.BuscarDatos(data.miID + "new");

            for (int i = 0; i < misNuevasBalas.Count; i++)
            {
                cmdParametres += "~1";
            }

            cmd.data.command = cmdParametres;
            debugin = data.sockOUT.Send(cmd.outByte());

            //ahora envio los paquetes con los datos de los disparos

            foreach (KeyValuePair<string, CDataGameBase> item in misNuevasBalas)
            {
                bala.data = (CBalasDatos) item.Value;
                debugin = data.sockOUT.Send(bala.outByte());
            }
            //elimino las nuevas balas enviadas
            SCPeticion.EliminarDatos("new");
             
        }

        static public void RecivirInfo()
        {
            byte[] buffByte = new byte[2048];
            int debugin = 0;

            pqCmd cmd = new pqCmd();
            pqActorMini actorMini = new pqActorMini();
            pqAsteoirdes asteoirde = new pqAsteoirdes();
            pqBalas balas = new pqBalas();

            string[] cmdParametros;

            //recibo los datos servidor y se almacenan localmente
            while (true)
            {
                debugin = data.sockIN.Receive(buffByte);
                //primero acepta un paquete cmd que indica que es lo que le esta por venir
                cmd.inByte(buffByte);

                if (cmd.data != null)
                    if (cmd.data.command != "")
                    {
                        cmdParametros = cmd.getParametres();

                        for (int y = 1; y < cmdParametros.Length; y++)
                        {
                            switch (cmdParametros[y])
                            {
                                //Todos los tipos de paquetes esperados

                                //pqActorDatosMini
                                case "0":
                                    debugin = data.sockIN.Receive(buffByte);
                                    actorMini.inByte(buffByte);
                                    datosMini.Add(actorMini.data);
                                    break;

                                //pqBalas
                                case "1":
                                    debugin = data.sockIN.Receive(buffByte);
                                    balas.inByte(buffByte);
                                    Disparos.Add(balas.data);
                                    break;
                            }
                        }
                    }
            }
        }     */               
        #endregion

        static public void EnviarInfo2()
        {
            pqCmd cmd = new pqCmd();
            CBalasDatos bala = new CBalasDatos();

            int debugin = 0;
            string cmdString = "";

            while (true)
            {
                Dictionary<string, CDataGameBase> balas = SCPeticion.BuscarDatos("new");
                //2° Armo el cmd de las balas            
                foreach (KeyValuePair<string, CDataGameBase> item in balas)
                {
                    cmdString = "1~";

                    bala = (CBalasDatos)item.Value;
                    cmdString += bala.ClienteDunio + "~";
                    cmdString += bala.posicionActual.X + "~";
                    cmdString += bala.posicionActual.Y + "~";
                    cmdString += bala.posicionAnterior.X + "~";
                    cmdString += bala.posicionAnterior.Y + "~";
                    cmdString += bala.name;

                    cmd.data.command = cmdString;

                    debugin = data.sockOUT.Send(cmd.outByte());
                }
                //elimino las nuevas balas

                SCPeticion.EliminarDatos("new");
            }
        }

        static void RecivirInfo2()
        {
            pqCmd cmd = new pqCmd();
            pqBalas bala = new pqBalas(); // 1 
            pqAsteoirdes asteroide = new pqAsteoirdes(); // 2
            pqActorMini actorMini = new pqActorMini(); // 0

            CBalasDatos balaDatos = new CBalasDatos();

            byte[] buffByte = new byte[2048];
            int debugin = 0;

            string[] cmdParametres;
            string cmdString = "";

            while (true)
            {
               debugin = data.sockIN.Receive(buffByte);
               cmd.inByte(buffByte);

               if (cmd.data != null)
               {
                   cmdParametres = cmd.getParametres();

                   //espero recibir balas
                   if (cmdParametres[0] == "1")
                   {
                       if (cmdParametres[1] == "Datos")
                       {
                           balaDatos.ClienteDunio = int.Parse(cmdParametres[2]);
                           balaDatos.posicionActual.X = int.Parse(cmdParametres[3]);
                           balaDatos.posicionActual.Y = int.Parse(cmdParametres[4]);
                           balaDatos.name = cmdParametres[5];
                       }

                       //agrego la nueva bala a las peticiones
                       if (SCPeticion.DatosGame.ContainsKey(balaDatos.name))
                       {
                           SCPeticion.EliminarDatos(balaDatos.name);
                       }
                       SCPeticion.DatosGame.Add(balaDatos.name, balaDatos);
                   }
               }
            }
        }
    }
}
